项目需要使用 art-template 进行前端渲染,本想直接使用 Vue ,不过项目渲染不多,还是学习下 art-template吧,提前踩踩坑,避免用在项目上的时候出现问题。用的时候了解到 art-template 好像是腾讯团队开发维护的,感觉文档要糟糕,不出所料在文档上遇到一些问题。

art-template使用笔记

art-template 是前端的一个高性能 JavaScript 模板引擎,它采用作用域预声明的技术来优化模板渲染速度,从而获得接近 JavaScript 极限的运行性能。

通过下面一张图可以大致了解下 art-template 与其他方式渲染HTML页面的性能比较:

具体跟 Vue、React 这些前端主流框架比较的性能,官方并未给出数据,但是我认为只比较页面渲染能力的话,应该相差不多, Vue、React 是一整套的前端解决方案,而 art-template 只是一个 js模板引擎,二者定位和功能不同,不做详细比较,猜测 art-template 同样是使用虚拟 DOM 的方式进行页面渲染,否则能达到这样的性能,着实不容易。就学习而言,如果学习过 Vue、React,学这个非常简单,反过来学会 art-template 对学习 Vue、React也有一定帮助。

在网上查询资料的时候,发现 art-template 好像是腾讯团队开发开源的,了解到这个情况的时候,心中少不了吐槽,不可否认东西确实好用,但是架不住腾讯团队写的文档烂啊!!腾讯团队什么时候能在文档上面长点心,学学隔壁的阿里。废话不多说了,简单写下容易遇到的问题。

初始化问题

关于 art-template 模板编写语法很简洁; template 对象的初始化也非常简单,只有两行代码,

模板编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script id="art-template" type="text/html">
<table>
/******/
<tbody>
{{each classInfoList}}
<tr>
<td>{{$index+1}}</td>
<td>{{$value.Id}}</td>
<td>{{$value.Name}}</td>
<td>{{$value.Teacher}}</td>
<td>{{$value.Remark}}</td>
<td>
<a href="{{$value.Uri}}">删除</a>
</td>
</tr>
{{/each}}
</tbody>
</table>
</script>

template对象初始化:

1
2
var html = template("art-template", datas);
document.getElementById('app').innerHTML = html;
  • "art-template" 是定义好的模板的 id
  • datas 是需要渲染的数据

JS执行时间、顺序问题

在网上找到的 Demo 大多都是在 js 里面写一个假数据,用定义好的数据去初始化 template 对象,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE HTML> 
<html>
<head>
<meta charset="UTF-8">
<title>basic-demo</title>
<script src="../dist/template.js"></script>
</head>
<body>
<div id="content"></div>
<script id="test" type="text/html">
{{if isAdmin}}
<h1>{{title}}</h1>
<ul>
{{each list as value i}}
<li>索引 {{i + 1}} :{{value}}</li>
{{/each}}
</ul>
{{/if}}
</script>
<script>
var data = {
title: '基本例子',
isAdmin: true,
list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;
</script>
</body>
</html>

因为以前主要使用 Vue ,Vue 是有动态渲染,但是忘记了这个并没有提到是动态渲染,同时项目开发时,数据大多通过 Ajax 从后台获取,因此在开始时,将 template 对象初始化放在了 ajax 回调函数外,因为 ajax 请求数据需要花费时间,同时js代码跟后台代码执行顺序不同,并不是按行数依次执行,所以前期导致一直渲染失败。应注意 js 代码执行顺序和执行时间的问题。

完整ajax代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var datas = {
title: "",
classInfoList: []
}
$.ajax({
type: "GET",
dataType:"JSON",
url: "/ClassHandler.ashx",
success: function (data) {
//原生JS序列化JSOn
//datas.classInfoList = JSON.parse(data).classInfoList;
datas.classInfoList = data.classInfoList;
datas.title =data.title;
html = template("art-template", datas);
document.getElementById('app').innerHTML = html;
}
})

template数据初始化问题

在上面也看到,序列化 template 对象一共传了两个参数,一个是模板的 Id,另外一个是数据。

但是这个数据有个一问题,如果返回回来的 JSON 数据是类似数组数据的话,是没有办法直接渲染的,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[{
"Id": 0,
"Name": "班级0",
"Teacher": "教师0",
"Remark": "这是班级0的简介",
"Uri": "/deleteClass.ashx?id=0"
}, {
"Id": 1,
"Name": "班级1",
"Teacher": "教师1",
"Remark": "这是班级1的简介",
"Uri": "/deleteClass.ashx?id=1"
}, {
"Id": 2,
"Name": "班级2",
"Teacher": "教师2",
"Remark": "这是班级2的简介",
"Uri": "/deleteClass.ashx?id=2"
}]

这个样子是没有办法直接进行渲染,需要对数据如上述代码块包装,才能正常渲染。

如果返回 JSON 数据为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"classInfoList": [{
"Id": 0,
"Name": "班级0",
"Teacher": "教师0",
"Remark": "这是班级0的简介",
"Uri": "/deleteClass.ashx?id=0"
}, {
"Id": 1,
"Name": "班级1",
"Teacher": "教师1",
"Remark": "这是班级1的简介",
"Uri": "/deleteClass.ashx?id=1"
}, {
"Id": 2,
"Name": "班级2",
"Teacher": "教师2",
"Remark": "这是班级2的简介",
"Uri": "/deleteClass.ashx?id=2"
}],
"title": "软件学院班级列表"
}

可以直接初始化 template 对象,并进行渲染(模板不变)

1
2
3
4
5
6
7
8
9
10
11
<script>
$.ajax({
type: "GET",
dataType:"JSON",
url: "/ClassHandler.ashx",
success: function (data) {
html = template("art-template", data);
document.getElementById('app').innerHTML = html;
}
})
</script>

template 对象初始化需注意地方

API:template(filename, content)

根据模板名渲染模板。

  • 参数:
    • {string} filename
    • {Object,string} content
  • 返回值:
    • 如果 contentObject,则渲染模板并返回 string
    • 如果 contentstring,则编译模板并返回 function

浏览器版本无法加载外部文件,filename 为存放模板的元素 id

因为渲染的时候,数据大多从后台获取,后台返回的数据可能为字符串或JSON,如果第二个参数(content)传进来的是字符串的话,没有报错,但是渲染会失败,渲染结果如下:

image
image

因此,需注意 template 初始化赋值时,数据格式是否正确。

渲染问题

each 循环渲染问题

关于循环的语法,官方文档上写的很简洁:

image
image

默认在遍历 target 时,有两个值,value和index,其中 value 是单个对象值,index 是下标。

根据文档所写,我把

1
2
3
4
5
6
7
8
9
10
11
12
{{each classInfoList}}
<tr>
<td>{{$index+1}}</td>
<td>{{$value.Id}}</td>
<td>{{$value.Name}}</td>
<td>{{$value.Teacher}}</td>
<td>{{$value.Remark}}</td>
<td>
<a href="{{$value.Uri}}">删除</a>
</td>
</tr>
{{/each}}

修改为:

1
2
3
4
5
6
7
8
9
10
11
12
{{each classInfoList val key}}
<tr>
<td>{{$key+1}}</td>
<td>{{$val.Id}}</td>
<td>{{$val.Name}}</td>
<td>{{$val.Teacher}}</td>
<td>{{$val.Remark}}</td>
<td>
<a href="{{$val.Uri}}">删除</a>
</td>
</tr>
{{/each}}

浏览器在渲染的时候就报错了:

image
image

至今不清楚,是我没领会文档说明,还是 art-template 团队忘了维护文档了。

结语

本文只是 art-template js模板引擎的简单使用,还有其他几个接口、方式没有逐一介绍,在我看来这些已经能够满足基本的开发使用,至于更加复杂的渲染、渲染切换,Vue 比 art-template 省心。如有兴趣继续研究 art-template ,附上官方文档及参考博客链接。


参考文档: